import asyncio
from typing import Dict, Union

from enums.modbus_register import RegisterType
from enums.protocol_type import TcpConfig, ProtocolType, RtuConfig
from service.log import log
from service.server.modbus_server import ModbusSerialServer, ModbusTcpServer, ModbusRtuOverTcpServer  # 假设存在该类
from db.controller.db_controller import db_controller


class ServerManager:
    def __init__(self):
        self.server_map: Dict[str, Union[ModbusSerialServer, ModbusTcpServer, ModbusRtuOverTcpServer]] = {}
        self.server_tasks: Dict[str, asyncio.Task] = {}

    def set_all_server(self):
        device_list = db_controller.device_dao.get_device_list()
        for device in device_list:
            device_name = device['name']
            ip = device['ip']
            port = device['port']
            protocol = device['protocol']
            if protocol == ProtocolType.TCP.value:
                self.add_modbus_tcp_server(device_name, ip, port)
            elif protocol == ProtocolType.RTU_OVER_TCP.value:
                self.add_modbus_rtu_over_tcp_server(device_name, ip, port)
            else:
                return

    def add_modbus_tcp_server(self, device_name: str, ip: str, port: int):
        if device_name not in self.server_map:
            tcp_config = TcpConfig(ip, port, ProtocolType.TCP)
            self.server_map[device_name] = ModbusTcpServer(server_address=tcp_config.host, port=tcp_config.port)

    def add_modbus_rtu_over_tcp_server(self, device_name: str, ip: str, port: int):
        if device_name not in self.server_map:
            tcp_config = TcpConfig(ip, port, ProtocolType.RTU_OVER_TCP)
            self.server_map[device_name] = ModbusRtuOverTcpServer(server_address=tcp_config.host, port=tcp_config.port)

    def add_modbus_rtu_server(self, device_name: str, port: str, baudrate: int, parity: str,
                              stopbits: int, bytesize: int, timeout: float):
        if device_name not in self.server_map:
            rtu_config = RtuConfig(port, baudrate, parity, stopbits, bytesize, timeout)
            self.server_map[device_name] = ModbusSerialServer(
                serial_port=rtu_config.port,
                baudrate=rtu_config.baudrate,
                parity=rtu_config.parity,
                stopbits=rtu_config.stopbits,
                bytesize=rtu_config.bytesize,
            )

    def edit_server(self, old_device_name: str, protocol_type: ProtocolType, device_name: str, ip: str,
                    port: int) -> None:
        try:
            self.delete_server(old_device_name)
            if protocol_type == ProtocolType.TCP:
                self.add_modbus_tcp_server(device_name, ip, port)
            elif protocol_type == ProtocolType.RTU_OVER_TCP:
                self.add_modbus_rtu_over_tcp_server(device_name, ip, port)
            else:
                return
        except Exception as e:
            log.error(f"编辑服务器失败: {e}")
            raise e

    def delete_server(self, device_name: str):
        log.info(f"删除服务器: {device_name}")
        if device_name in self.server_map:
            self.stop_server(device_name)
            del self.server_map[device_name]
            if device_name in self.server_tasks:
                del self.server_tasks[device_name]

    def get_server(self, device_name: str) -> Union[ModbusSerialServer, ModbusTcpServer, ModbusRtuOverTcpServer]:
        if device_name in self.server_map:
            return self.server_map[device_name]
        else:
            raise ValueError(f"未找到设备: {device_name}")

    async def _start_server_async(self, device_name: str):
        if device_name in self.server_map:
            try:
                await self.server_map[device_name].runAsyncServer()
            except Exception as e:
                log.error(f"服务器 {device_name} 启动失败: {e}")

    def start_server(self, device_name: str) -> bool:
        """
        异步启动指定名称的服务器

        :param device_name: 服务器设备名称
        """
        if device_name in self.server_map:
            if device_name in self.server_tasks and not self.server_tasks[device_name].done():
                log.warning(f"服务器 {device_name} 已经在运行中")
                return False
            loop = asyncio.get_running_loop()
            task = loop.create_task(self._start_server_async(device_name))
            self.server_tasks[device_name] = task
            log.info(f"成功启动服务器: {device_name}")
            return True
        else:
            log.error(f"未找到服务器: {device_name}，无法启动")
            return False

    def stop_server(self, device_name: str) -> bool:
        """
        停止指定名称的服务器

        :param device_name: 服务器设备名称
        """
        if device_name in self.server_map:
            self.server_map[device_name].stopServer()
            if device_name in self.server_tasks:
                task = self.server_tasks[device_name]
                if not task.done():
                    task.cancel()
                del self.server_tasks[device_name]
            log.info(f"成功停止服务器: {device_name}")
            return True
        else:
            log.error(f"未找到服务器: {device_name}，无法停止")
            return False

    def start_all_servers(self):
        """
        异步启动所有服务器
        """
        for device_name in self.server_map:
            self.start_server(device_name)

    def stop_all_servers(self):
        """
        停止所有服务器
        """
        for device_name in self.server_map:
            self.stop_server(device_name)

    def add_slave(self, device_name: str, slave_id: int) -> bool:
        """
        添加从站
        """
        if device_name in self.server_map:
            return self.server_map[device_name].add_slave(slave_id)
        return False

    def delete_slave(self, device_name: str, slave_id: int) -> bool:
        """
        删除从站
        """
        if device_name in self.server_map:
            return self.server_map[device_name].delete_slave(slave_id)
        return False

    def is_slave_exist(self, device_name: str, slave_id: int) -> bool:
        """
        检查从站是否存在
        """
        if device_name in self.server_map:
            return self.server_map[device_name].is_slave_exist(slave_id)
        return False

    def set_slave_address(self, device_name: str, slave_id: int, register_type: RegisterType, start_address: int,
                          end_address: int):
        """
        设置从站寄存器地址
        """
        if device_name in self.server_map:
            modbus_server = self.server_map[device_name]
            if register_type == RegisterType.COIL:
                modbus_server.add_slave_co(slave_id, start_address, end_address)
            elif register_type == RegisterType.DISCRETE_INPUT:
                modbus_server.add_slave_di(slave_id, start_address, end_address)
            elif register_type == RegisterType.INPUT_REGISTER:
                modbus_server.add_slave_ir(slave_id, start_address, end_address)
            elif register_type == RegisterType.HOLDING_REGISTER:
                modbus_server.add_slave_hr(slave_id, start_address, end_address)
